from PyQt5.QtCore import QObject, pyqtSignal, QThread, QByteArray
import serial
import serial.tools.list_ports
from collections import deque

class SerialComm(QObject):
    # 信号定义
    data_received = pyqtSignal(bytes)  # 接收到数据时触发
    connection_status = pyqtSignal(bool, str)  # 连接状态变化
    error_occurred = pyqtSignal(str)  # 错误信息

    def __init__(self, port=None, baudrate=115200, timeout=0.1):
        super().__init__()
        self.port = port
        self.baudrate = baudrate
        self.timeout = timeout
        self.serial_port = None
        self.running = False
        self.send_queue = deque()
        self.thread = QThread()
        
        # 将对象移动到独立线程
        self.moveToThread(self.thread)
        self.thread.started.connect(self.process)

    def start(self):
        """启动通信线程"""
        if not self.thread.isRunning():
            self.thread.start()

    def stop(self):
        """停止通信线程"""
        self.running = False
        self.close_port()
        if self.thread.isRunning():
            self.thread.quit()
            self.thread.wait()

    def open_port(self):
        """打开串口"""
        try:
            if self.serial_port and self.serial_port.is_open:
                self.close_port()

            self.serial_port = serial.Serial(
                port=self.port,
                baudrate=self.baudrate,
                timeout=self.timeout,
                write_timeout=self.timeout
            )
            self.running = True
            self.connection_status.emit(True, f"Connected to {self.port}")
            return True
        except Exception as e:
            self.error_occurred.emit(f"串口打开失败: {str(e)}")
            self.connection_status.emit(False, "Disconnected")
            return False

    def close_port(self):
        """关闭串口"""
        if self.serial_port and self.serial_port.is_open:
            self.serial_port.close()
            self.running = False
            self.connection_status.emit(False, "Disconnected")

    def send_data(self, data):
        """发送数据（线程安全）"""
        if isinstance(data, str):
            data = data.encode('utf-8')
        self.send_queue.append(data)

    def process(self):
        """主循环处理"""
        self.running = True
        while self.running:
            try:
                # 处理发送队列
                if self.send_queue and self.serial_port and self.serial_port.is_open:
                    data = self.send_queue.popleft()
                    self.serial_port.write(data)

                # 读取数据
                if self.serial_port and self.serial_port.in_waiting > 0:
                    data = self.serial_port.read_all()
                    if data:
                        self.data_received.emit(data)

            except Exception as e:
                self.error_occurred.emit(f"通信错误: {str(e)}")
                self.close_port()

    @staticmethod
    def list_ports():
        """获取可用串口列表"""
        return [port.device for port in serial.tools.list_ports.comports()]

    def __del__(self):
        self.stop()